"""
实现链表类
挑战介绍
实现链表的插入，增加，查找，删除，查看长度和打印的方法。链表的介绍如下：

链表是一种物理存储单元上非连续、非顺序的存储结构，数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表中每一个元素称为结点，链表由一系列结点组成，结点可以在运行时动态生成。
链表的每个结点包括两个部分：一个是存储数据元素的数据域，另一个是存储下一个结点地址的指针域。
链表结构图解

挑战内容
本次挑战中，你需要在 linkedlist.py 文件中补充类 Node 和类 LinkedList 的空缺部分。
Node 类是定义的结点类。
Node 中的 __init__ 方法用于初始化结点，结点包含数据元素 data 和指向下一个结点地址的指针 next_node。
Node 中的 __str__ 方法用于返回当使用 print 输出对象时打印的信息，它需要返回结点的数据元素。
LinkedList 类是定义的链表类。
LinkedList 中的 __init__ 方法用于初始化链表，参数 head 为链表头的指针。
LinkedList 中的 __len__ 方法用于返回链表的结点个数，它需要返回一个数字。
LinkedList 中的 insert_to_front 方法用于在链表前面插入结点，参数 data 用于指定结点的数据元素，它需要返回插入的结点。如果 data 为 None 则返回 None。
LinkedList 中的 append 方法用于在链表后面增加结点，参数 data 用于指定结点的数据元素，它需要返回增加的结点。如果 data 为 None 则返回 None。
LinkedList 中的 find 方法用于查找链表中包含指定数据元素的结点，参数 data 用于指定结点的数据元素，它需要返回找到的结点。如果无法找到数据，则返回 None。
LinkedList 中的 delete 方法用于删除链表中包含指定数据元素的结点，参数 data 用于指定结点的数据元素，它不需要返回任何值。如果链表没有结点，或者指定元素不在链表中，则不进行删除操作。
LinkedList 中的 print_list 方法用于打印链表所有结点的数据元素。它需要使用 print 函数从链表头至链表尾依次打印出结点的数据元素。
LinkedList 中的 get_all_data 方法用于将链表转化为数组，数组的元素为链表结点的数据元素，它需要返回一个数组。
"""


class Node(object):

    def __init__(self, data, next=None):
        self.next = next
        self.data = data

    def __str__(self):
        return self.data


class LinkedList(object):

    def __init__(self, head=None):
        self.head = head

    def __len__(self):
        curr = self.head
        counter = 0
        while curr is not None:
            counter += 1
            curr = curr.next
        return counter

    def insert_to_front(self, data):
        if data is None:
            return None
        node = Node(data, self.head)
        self.head = node
        return node

    def append(self, data):
        if data is None:
            return None
        node = Node(data)
        if self.head is None:
            self.head = node
            return node
        curr_node = self.head
        while curr_node.next is not None:
            curr_node = curr_node.next
        curr_node.next = node
        return node

    def find(self, data):
        if data is None:
            return None
        curr_node = self.head
        while curr_node is not None:
            if curr_node.data == data:
                return curr_node
            curr_node = curr_node.next
        return None

    def delete(self, data):
        if data is None:
            return
        if self.head is None:
            return
        if self.head.data == data:
            self.head = self.head.next
            return
        prev_node = self.head
        curr_node = self.head.next
        while curr_node is not None:
            if curr_node.data == data:
                prev_node.next = curr_node.next
                return
            prev_node = curr_node
            curr_node = curr_node.next

    def print_list(self):
        curr_node = self.head
        while curr_node is not None:
            print(curr_node.data)
            curr_node = curr_node.next

    def get_all_data(self):
        data = []
        curr_node = self.head
        while curr_node is not None:
            data.append(curr_node.data)
            curr_node = curr_node.next
        return data
